using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Terra.Data.Repository;
using Terra.Data.Entities.Identity;
using Terra.Core.Common.Enums.Identity;
using Terra.Core.Common.Models.Pagination;
using Terra.Data.Models.Identity;

namespace Terra.Data.Repository.Identity;

/// <summary>
/// 用户仓储接口
/// </summary>
public interface IUserRepository : IRepository<User, Guid>
{
    /// <summary>
    /// 密码选项
    /// </summary>
    PasswordOptions Options { get; }

    /// <summary>
    /// 根据用户名查找用户
    /// </summary>
    /// <param name="userName">用户名</param>
    /// <param name="includeRoles">是否包含角色信息</param>
    /// <returns>用户信息</returns>
    Task<User> FindByNameAsync(string userName, bool includeRoles = false);

    /// <summary>
    /// 根据邮箱查找用户
    /// </summary>
    /// <param name="email">邮箱</param>
    /// <param name="includeRoles">是否包含角色信息</param>
    /// <returns>用户信息</returns>
    Task<User> FindByEmailAsync(string email, bool includeRoles = false);

    /// <summary>
    /// 根据手机号查找用户
    /// </summary>
    /// <param name="phoneNumber">手机号</param>
    /// <param name="includeRoles">是否包含角色信息</param>
    /// <returns>用户信息</returns>
    Task<User> FindByPhoneNumberAsync(string phoneNumber, bool includeRoles = false);

    /// <summary>
    /// 根据用户名/邮箱/手机号查找用户
    /// </summary>
    /// <param name="identifier">标识符</param>
    /// <returns>用户实体</returns>
    Task<User> FindByUsernameOrEmailOrPhoneAsync(string identifier);

    /// <summary>
    /// 获取用户的角色列表
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <returns>角色列表</returns>
    Task<IList<Role>> GetRolesAsync(Guid userId);

    /// <summary>
    /// 获取用户的声明列表
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <returns>声明列表</returns>
    Task<IList<UserClaim>> GetClaimsAsync(Guid userId);

    /// <summary>
    /// 根据用户名获取用户
    /// </summary>
    Task<User> GetByUsernameAsync(string username);

    /// <summary>
    /// 根据邮箱获取用户
    /// </summary>
    Task<User> GetByEmailAsync(string email);

    /// <summary>
    /// 根据手机号获取用户
    /// </summary>
    Task<User> GetByPhoneAsync(string phone);

    /// <summary>
    /// 创建用户
    /// </summary>
    /// <param name="user">用户实体</param>
    /// <param name="password">密码</param>
    /// <returns>用户实体</returns>
    Task<User> CreateAsync(User user, string password);

    /// <summary>
    /// 验证密码
    /// </summary>
    /// <param name="user">用户实体</param>
    /// <param name="password">密码</param>
    /// <returns>是否验证成功</returns>
    bool ValidatePassword(User user, string password);

    /// <summary>
    /// 验证密码重置令牌
    /// </summary>
    /// <param name="token">令牌</param>
    /// <returns>验证结果</returns>
    Task<(bool Succeeded, Guid UserId)> VerifyPasswordResetTokenAsync(string token);

    /// <summary>
    /// 重置密码
    /// </summary>
    /// <param name="user">用户实体</param>
    /// <param name="token">令牌</param>
    /// <param name="newPassword">新密码</param>
    /// <returns>重置结果</returns>
    Task<IdentityResult> ResetPasswordAsync(User user, string token, string newPassword);

    /// <summary>
    /// 检查用户是否设置了密码
    /// </summary>
    /// <param name="user">用户实体</param>
    /// <returns>是否设置了密码</returns>
    Task<bool> HasPasswordAsync(User user);

    /// <summary>
    /// 检查密码是否正确
    /// </summary>
    /// <param name="user">用户实体</param>
    /// <param name="password">密码</param>
    /// <returns>是否正确</returns>
    Task<bool> CheckPasswordAsync(User user, string password);

    /// <summary>
    /// 修改密码
    /// </summary>
    /// <param name="user">用户实体</param>
    /// <param name="currentPassword">当前密码</param>
    /// <param name="newPassword">新密码</param>
    /// <returns>修改结果</returns>
    Task<IdentityResult> ChangePasswordAsync(User user, string currentPassword, string newPassword);

    /// <summary>
    /// 设置用户密码
    /// </summary>
    /// <param name="user">用户实体</param>
    /// <param name="password">密码</param>
    /// <returns>设置结果</returns>
    Task<IdentityResult> SetPasswordAsync(User user, string password);

    /// <summary>
    /// 创建密码重置令牌
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <param name="token">令牌</param>
    /// <param name="resetType">重置类型</param>
    /// <param name="expiresAt">过期时间</param>
    /// <returns>密码重置令牌实体</returns>
    Task<PasswordResetToken> CreatePasswordResetTokenAsync(Guid userId, string token, ResetType resetType, DateTime expiresAt);

    /// <summary>
    /// 获取有效的密码重置令牌
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <param name="token">令牌</param>
    /// <returns>密码重置令牌实体</returns>
    Task<PasswordResetToken> GetValidPasswordResetTokenAsync(Guid userId, string token);

    /// <summary>
    /// 使密码重置令牌失效
    /// </summary>
    /// <param name="token">密码重置令牌实体</param>
    Task InvalidatePasswordResetTokenAsync(PasswordResetToken token);

    /// <summary>
    /// 更新用户密码
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <param name="passwordHash">密码哈希</param>
    /// <param name="passwordSalt">密码盐</param>
    Task UpdatePasswordAsync(Guid userId, string passwordHash, string passwordSalt);

    /// <summary>
    /// 检查用户名是否存在
    /// </summary>
    /// <param name="userName">用户名</param>
    /// <param name="excludeUserId">排除的用户ID</param>
    /// <returns>是否存在</returns>
    Task<bool> IsUserNameExistsAsync(string userName, Guid? excludeUserId = null);

    /// <summary>
    /// 检查邮箱是否存在
    /// </summary>
    /// <param name="email">邮箱</param>
    /// <param name="excludeUserId">排除的用户ID</param>
    /// <returns>是否存在</returns>
    Task<bool> IsEmailExistsAsync(string email, Guid? excludeUserId = null);

    /// <summary>
    /// 检查手机号是否存在
    /// </summary>
    /// <param name="phoneNumber">手机号</param>
    /// <param name="excludeUserId">排除的用户ID</param>
    /// <returns>是否存在</returns>
    Task<bool> IsPhoneNumberExistsAsync(string phoneNumber, Guid? excludeUserId = null);

    /// <summary>
    /// 分页查询用户
    /// </summary>
    /// <param name="query">查询条件</param>
    /// <returns>分页结果</returns>
    Task<IPagedList<User>> GetPagedListAsync(UserQueryDto query);

    /// <summary>
    /// 获取用户详情
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <param name="includeRoles">是否包含角色信息</param>
    /// <returns>用户详情</returns>
    Task<User> GetUserDetailAsync(Guid userId, bool includeRoles = true);

    /// <summary>
    /// 为用户分配角色
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <param name="roleIds">角色ID列表</param>
    /// <returns>操作结果</returns>
    Task<bool> AssignRolesToUserAsync(Guid userId, List<Guid> roleIds);

    /// <summary>
    /// 获取用户的角色ID列表
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <returns>角色ID列表</returns>
    Task<List<Guid>> GetUserRoleIdsAsync(Guid userId);

    /// <summary>
    /// 获取用户的角色名称列表
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <returns>角色名称列表</returns>
    Task<List<string>> GetUserRoleNamesAsync(Guid userId);


    /// <summary>
    /// 根据条件获取用户列表
    /// </summary>
    /// <param name="predicate">查询条件</param>
    /// <returns>用户列表</returns>
    new Task<List<User>> GetListAsync(Expression<Func<User, bool>> predicate);

    /// <summary>
    /// 检查用户名是否已存在
    /// </summary>
    /// <param name="userName">用户名</param>
    /// <returns>是否存在</returns>
    Task<bool> ExistsByUsernameAsync(string userName);

    /// <summary>
    /// 检查邮箱是否已存在
    /// </summary>
    /// <param name="email">邮箱</param>
    /// <returns>是否存在</returns>
    Task<bool> ExistsByEmailAsync(string email);

    /// <summary>
    /// 检查手机号是否已存在
    /// </summary>
    /// <param name="phoneNumber">手机号</param>
    /// <returns>是否存在</returns>
    Task<bool> ExistsByPhoneNumberAsync(string phoneNumber);
}